import { Visualizer } from '../src/components/Visualizer.js';
import * as algorithms from '../src/algorithms/index.js';
import { WebMRecorder } from '../src/utils/GIFRecorder.js';

class SortingApp {
    constructor() {
        this.visualizer = new Visualizer(document.getElementById('canvas'));
        this.isSorting = false;
        this.startTime = 0;
        this.comparisons = 0;
        this.swaps = 0;
        this.recorder = new WebMRecorder(document.getElementById('canvas'));
        this.isRecording = false;
        
        this.initializeControls();
        this.generateArray();
    }

    initializeControls() {
        this.algorithmSelect = document.getElementById('algorithm');
        this.sizeSlider = document.getElementById('array-size');
        this.sizeValue = document.getElementById('size-value');
        this.speedSlider = document.getElementById('speed');
        this.speedValue = document.getElementById('speed-value');
        this.generateBtn = document.getElementById('generate-array');
        this.startBtn = document.getElementById('start-sort');
        this.stopBtn = document.getElementById('stop-sort');
        this.comparisonsEl = document.getElementById('comparisons');
        this.swapsEl = document.getElementById('swaps');
        this.timeEl = document.getElementById('time');

        this.sizeSlider.addEventListener('input', (e) => {
            this.sizeValue.textContent = e.target.value;
            if (!this.isSorting) {
                this.generateArray();
            }
        });

        this.speedSlider.addEventListener('input', (e) => {
            this.speedValue.textContent = e.target.value + 'x';
        });

        this.generateBtn.addEventListener('click', () => {
            if (!this.isSorting) {
                this.generateArray();
            }
        });

        this.startBtn.addEventListener('click', () => {
            this.startSorting();
        });

        this.stopBtn.addEventListener('click', () => {
            this.stopSorting();
        });

        const recordBtn = document.getElementById('record-gif');
        const downloadBtn = document.getElementById('download-gif');
        
        recordBtn.addEventListener('click', () => {
            this.toggleRecording();
        });

        downloadBtn.addEventListener('click', () => {
            this.downloadRecording();
        });
    }

    generateArray() {
        const size = parseInt(this.sizeSlider.value);
        this.visualizer.generateArray(size);
        this.resetStats();
    }

    resetStats() {
        this.comparisons = 0;
        this.swaps = 0;
        this.startTime = 0;
        this.comparisonsEl.textContent = '0';
        this.swapsEl.textContent = '0';
        this.timeEl.textContent = '0ms';
    }

    async startSorting() {
        if (this.isSorting) return;

        this.isSorting = true;
        this.startBtn.disabled = true;
        this.stopBtn.disabled = false;
        this.generateBtn.disabled = true;
        
        this.startTime = Date.now();
        const algorithm = this.algorithmSelect.value;
        const algorithmFunction = algorithms[algorithm + 'Sort'];
        
        if (!algorithmFunction) {
            console.error('Algorithm not found:', algorithm);
            return;
        }

        try {
            await this.runAlgorithm(algorithmFunction);
            this.visualizer.markSorted();
        } catch (error) {
            if (error.message !== 'Sorting stopped') {
                console.error('Error during sorting:', error);
            }
        } finally {
            this.stopSorting();
        }
    }

    stopSorting() {
        this.isSorting = false;
        this.startBtn.disabled = false;
        this.stopBtn.disabled = true;
        this.generateBtn.disabled = false;
    }

    async toggleRecording() {
        const recordBtn = document.getElementById('record-gif');
        const downloadBtn = document.getElementById('download-gif');
        
        if (!this.isRecording) {
            this.isRecording = true;
            recordBtn.textContent = 'Stop Recording';
            recordBtn.style.background = '#ff6b6b';
            downloadBtn.disabled = true;
            
            const success = await this.recorder.start();
            if (!success) {
                this.isRecording = false;
                recordBtn.textContent = 'Record GIF';
                recordBtn.style.background = '#667eea';
                downloadBtn.disabled = true;
            }
        } else {
            this.isRecording = false;
            recordBtn.textContent = 'Record GIF';
            recordBtn.style.background = '#667eea';
            
            this.recorder.stop();
            downloadBtn.disabled = false;
        }
    }

    downloadRecording() {
        const algorithm = this.algorithmSelect.value;
        const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
        const filename = `${algorithm}-sort-${timestamp}.webm`;
        
        this.recorder.download(filename);
    }

    async runAlgorithm(algorithm) {
        const array = this.visualizer.array;
        const speed = 1000 / parseInt(this.speedSlider.value);

        const compare = async (i, j, val1, val2) => {
            if (!this.isSorting) throw new Error('Sorting stopped');
            
            this.comparisons++;
            this.comparisonsEl.textContent = this.comparisons;
            this.timeEl.textContent = (Date.now() - this.startTime) + 'ms';
            
            return await this.visualizer.compare(i, j, val1, val2);
        };

        const swap = async (i, j) => {
            if (!this.isSorting) throw new Error('Sorting stopped');
            
            this.swaps++;
            this.swapsEl.textContent = this.swaps;
            this.timeEl.textContent = (Date.now() - this.startTime) + 'ms';
            
            await this.visualizer.swap(i, j);
        };

        const set = async (index, value) => {
            if (!this.isSorting) throw new Error('Sorting stopped');
            
            await this.visualizer.set(index, value);
        };

        const generator = algorithm(array, compare, swap, set);
        
        for await (const step of generator) {
            if (!this.isSorting) break;
            
            switch (step.type) {
                case 'compare':
                    this.visualizer.highlight(step.indices, 'comparing');
                    break;
                case 'swap':
                    this.visualizer.highlight(step.indices, 'swapping');
                    break;
                case 'set':
                    this.visualizer.highlight([step.index], 'sorted');
                    break;
                case 'complete':
                    break;
            }
            
            await new Promise(resolve => {
                setTimeout(resolve, speed);
            });
        }
    }
}

document.addEventListener('DOMContentLoaded', () => {
    new SortingApp();
});